package org.feichao.xdao.util;

import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * 对象成员setter和getter调用封装工具，优先调用set和get的方法
 * @author chao
 * @since 2015/5/27
 */
public class FieldAccessUtil {

    /**
     * 获取
     *
     * @param obj
     * @param fieldName
     * @return
     */
    public static Object getter(Object obj, String fieldName){
        String getterName = "get"+ StringUtils.capitalize(fieldName);
        Class target = obj.getClass();
        try {
            Method getterMethod = target.getMethod(getterName);
            try {
                return getterMethod.invoke(obj);
            } catch (Exception e) {
                try {
                    Field field = target.getField(fieldName);
                    try {
                        return field.get(obj);
                    } catch (IllegalAccessException e1) {
                        throw new RuntimeException("Cannot get value from field:"+target.getCanonicalName() + "." + fieldName,e1);
                    }
                } catch (NoSuchFieldException e1) {
                    throw new RuntimeException("No such field:"+target.getCanonicalName() + "." + fieldName,e1);
                }
            }
        } catch (NoSuchMethodException e) {
            try {
                Field field = target.getField(fieldName);
                try {
                    return field.get(obj);
                } catch (IllegalAccessException e1) {
                    throw new RuntimeException("Cannot get value from field:"+target.getCanonicalName() + "." + fieldName,e1);
                }
            } catch (NoSuchFieldException e1) {
                throw new RuntimeException("No such field:"+target.getCanonicalName() + "." + fieldName,e1);
            }
        }
    }

    /**
     * 设置
     *
     * @param obj
     * @param fieldName
     * @param newVal
     */
    public static void setter(Object obj, String fieldName, Object newVal){
        if(newVal == null){
            return;
        }
        String setterName = "set"+ StringUtils.capitalize(fieldName);
        Class target = obj.getClass();
        try {
            Method setterMethod = target.getMethod(setterName);
            try {
                setterMethod.invoke(obj, newVal);
            } catch (Exception e) {
                try {
                    Field field = target.getField(fieldName);
                    try {
                        field.set(obj, newVal);
                    } catch (IllegalAccessException e1) {
                        throw new RuntimeException("Cannot set value to field:"+target.getCanonicalName() + "." + fieldName,e1);
                    }
                } catch (NoSuchFieldException e1) {
                    throw new RuntimeException("No such field:"+target.getCanonicalName() + "." + fieldName,e1);
                }
            }
        } catch (NoSuchMethodException e) {
            try {
                Field field = target.getField(fieldName);
                Object theNewVal = newVal;
                if(newVal instanceof BigDecimal){ //MySQL的ResultSet返回的可能是BigDecimal
                    BigDecimal num = (BigDecimal) newVal;
                    if(field.getType().equals(Integer.class) || field.getType().equals(int.class)){
                        theNewVal = num.intValue();
                    }else if(field.getType().equals(Long.class) || field.getType().equals(long.class)){
                        theNewVal = num.longValue();
                    }else if(field.getType().equals(Double.class) || field.getType().equals(double.class)){
                        theNewVal = num.doubleValue();
                    }else if(field.getType().equals(Float.class) || field.getType().equals(float.class)){
                        theNewVal = num.floatValue();
                    }else if(field.getType().equals(Byte.class) || field.getType().equals(byte.class)){
                        theNewVal = num.byteValue();
                    }
                } else if(newVal instanceof BigInteger){ //MySQL的ResultSet返回的可能是BigDecimal
                    BigInteger num = (BigInteger) newVal;
                    if(field.getType().equals(Integer.class) || field.getType().equals(int.class)){
                        theNewVal = num.intValue();
                    }else if(field.getType().equals(Long.class) || field.getType().equals(long.class)){
                        theNewVal = num.longValue();
                    }else if(field.getType().equals(Double.class) || field.getType().equals(double.class)){
                        theNewVal = num.doubleValue();
                    }else if(field.getType().equals(Float.class) || field.getType().equals(float.class)){
                        theNewVal = num.floatValue();
                    }else if(field.getType().equals(Byte.class) || field.getType().equals(byte.class)){
                        theNewVal = num.byteValue();
                    }
                }else{
                    if((field.getType().equals(Integer.class) || field.getType().equals(int.class)) && newVal instanceof Long){
                        long num = (Long) newVal;
                        theNewVal = (int) num;
                    }
                }
                try {
                    field.set(obj, theNewVal);
                } catch (IllegalAccessException e1) {
                    throw new RuntimeException("Cannot set value to field:"+target.getCanonicalName() + "." + fieldName,e1);
                }
            } catch (NoSuchFieldException e1) {
                throw new RuntimeException("No such field:"+target.getCanonicalName() + "." + fieldName,e1);
            }
        }
    }


}
